home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume2
/
intuitin
/
snipit12.1
< prev
next >
Wrap
Text File
|
1988-12-11
|
53KB
|
2,268 lines
Path: xanth!nic.MR.NET!tank!ncar!mailrus!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v02i095: snipit - cut/paste text from/to window with mouse v1.2
Message-ID: <10646@swan.ulowell.edu>
Date: 11 Dec 88 05:47:15 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 2257
Approved: page@swan.ulowell.edu
Submitted-by: scott@applix.uucp (Scott Evernden)
Posting-number: Volume 2, Issue 95
Archive-name: intuition/snipit12.1
- SnipIt 1.2 -
SnipIt is an input handler wedge which allows
you to clip text from any window, and then paste
that text anywhere, as though you had typed it
on the keyboard.
New in SnipIt 1.2 are the following:
o Now attempts to work in all windows and consoles.
P-Edit and VT100 now can be snipped from.
o Automatically detaches itself and runs in the
background- no Run/RunBack required.
o Built-in mini help (type: snipit h).
o Keyboard option to insert a short string at the
beginning of each pasted line.
o Options to move/adjust/correct snip/recognizer cell
area independently for consoles and windows.
o Can recognize highlighted text.
o Option to freeze window layer while snipping.
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# readme
# makefile
# hs.h
# detach.c
# hand.c
# main.c
# patch.c
# reco.c
# snipit.keys
# patch.doc
# snipit.doc
# This archive created: Sun Dec 11 00:43:21 1988
cat << \SHAR_EOF > readme
- SnipIt 1.2 -
SnipIt is an input handler wedge which allows
you to clip text from any window, and then paste
that text anywhere, as though you had typed it
on the keyboard.
New in SnipIt 1.2 are the following:
o Now attempts to work in all windows and consoles.
P-Edit and VT100 now can be snipped from.
o Automatically detaches itself and runs in the
background- no Run/RunBack required.
o Built-in mini help (type: snipit h).
o Keyboard option to insert a short string at the
beginning of each pasted line.
o Options to move/adjust/correct snip/recognizer cell
area independently for consoles and windows.
o Can recognize highlighted text.
o Option to freeze window layer while snipping.
- Scott Evernden
SHAR_EOF
cat << \SHAR_EOF > makefile
CFLAG =
LFLAGS = -w
CFLAGS = $(CFLAG) +ihs.i
OBJS = main.o hand.o reco.o
snipit: $(OBJS) detach.o
ln $(LFLAGS) -o $* $(OBJS) detach.o -lc
beep
detach.o: detach.c
$(OBJS): hs.i
hs.i: hs.h
cc -o nil: +hhs.i hs.h
final:
@make LFLAGS=
SHAR_EOF
cat << \SHAR_EOF > hs.h
#include <exec/types.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <exec/devices.h>
#include <exec/execbase.h>
#include <exec/interrupts.h>
#include <graphics/gfxbase.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <devices/conunit.h>
#include <devices/keymap.h>
#include <devices/input.h>
#include <devices/inputevent.h>
struct ConsoleBase {
struct Device conDevice;
char reserved[26];
struct List conUnits;
};
#include <functions.h>
/* mouse states */
#define M_UP 0
#define M_MOVE 1
#define M_DOWN 2
/* 'snip' container defines */
#define CON_SNIP 1
#define WIN_SNIP 2
#define PRE_SIZE 32
SHAR_EOF
cat << \SHAR_EOF > detach.c
/* Copyright (C) 1986,1987 by Manx Software Systems, Inc. */
/* Hacked up for SnipIt 1.2 use - Scott Evernden */
#include <exec/memory.h>
#include <libraries/dosextens.h>
#include <functions.h>
struct Process *_FindTask();
void *_AllocMem();
long _Open();
#define STACK_SIZE 3000L
extern BPTR output;
extern long running;
extern char *_procname;
extern char *_detach_name;
static long _alen = 0;
static char *_aptr = 0;
#asm
dseg
public __savsp
cseg
#endasm
do_detach(alen, aptr)
long *alen;
char **aptr;
{
register struct CommandLineInterface *cli;
register struct Process *pp;
register unsigned short c;
register char *cp;
register long l;
long *lp, *sav;
struct MemList *mm;
pp = _FindTask(0L);
/* first time through!! */
if (pp->pr_CLI) {
cli = (struct CommandLineInterface *) ((long)pp->pr_CLI << 2);
l = cli->cli_Module;
output = (BPTR) _Open("*", MODE_OLDFILE);
_alen = *alen;
_aptr = _AllocMem(_alen, 0L);
movmem(*aptr, _aptr, (int)_alen);
cp = (char *)((long)cli->cli_CommandName << 2);
_detach_name = AllocMem((long)cp[0]+1, 0L);
movmem(cp, _detach_name, cp[0]+1);
#asm
move.l __savsp,-(sp)
#endasm
cli->cli_Module = 0;
CreateProc(_procname, 0L, l, STACK_SIZE);
while (running == 0)
Delay(5L);
#asm
move.l (sp)+,sp
move.l #0,d0
rts
#endasm
}
/* second time through */
else if (strcmp(pp->pr_Task.tc_Node.ln_Name, _procname) == 0) {
lp = (long *)((long)pp->pr_SegList << 2);
lp = (long *)(lp[3] << 2);
sav = lp;
c = 2;
while (lp) {
lp = (long *)(*lp << 2);
c++;
}
mm = _AllocMem((long)sizeof(struct MemList)+
(c-1)*sizeof(struct MemEntry), 0L);
lp = sav;
mm->ml_NumEntries = c;
c = 0;
while (lp) {
mm->ml_me[c].me_Addr = (APTR)lp - 1;
mm->ml_me[c].me_Length = lp[-1];
lp = (long *)(*lp << 2);
c++;
}
mm->ml_me[c].me_Addr = (APTR)_aptr;
mm->ml_me[c++].me_Length = _alen;
mm->ml_me[c].me_Addr = (APTR)_detach_name;
mm->ml_me[c++].me_Length = _detach_name[0] + 1;
AddTail(&((struct Task *)pp)->tc_MemEntry, mm);
*alen = _alen;
*aptr = _aptr;
}
}
SHAR_EOF
cat << \SHAR_EOF > hand.c
/* :ts=4
*
* Amiga SnipIt 1.2
* (c) (opyright 1987,1988 - Scott Evernden - All Rights Reserved
*
* hand.c - input event handler & snipper & lib function replacements
*
*/
#include "hs.h"
int state; /* mouse state */
int snip; /* container type which is highlighted */
int maxx, maxy; /* maximum cells in snipped layer */
int origx, origy; /* pixel origin in conunit */
int charx, chary; /* pixel size of char cell of conunit */
int lastx, lasty; /* last cell highlighted */
int con_offx, con_offy; /* correction offsets for console windows */
int win_offx, win_offy; /* correction offsets for non-console windows */
int snipx[2], snipy[2]; /* snip area; top/left to bottom/right */
int left, right; /* sides of snip area, irrespective of rows */
struct TextFont *capttf; /* non-NULL indicates recognition required */
struct Window *snipw; /* clipped text window */
struct RastPort *sniprp; /* rastport of clipped text window */
struct RastPort captrp; /* rastport holding clipped snip area */
struct BitMap captbm; /* bitmap into which snipped area is copied */
int captx, capty; /* dimensions of capture map */
int jobFlag; /* flag input handler to ignore mouse events */
int lock_layer; /* lock window/console layer while snipping */
int windows=1; /* include windows in layer search */
int cmd1 = IEQUALIFIER_LCOMMAND;
int cmd2 = IEQUALIFIER_LALT;
extern struct IntuitionBase *IntuitionBase;
extern struct ConsoleBase *ConsoleBase;
extern struct Task *myTask;
extern int mySignal;
/* this does one at a time */
struct InputEvent *doEvent();
/*********************************************/
#asm
public _geta4
; Trap these Gfx/Intui functions; purpose is to remove hilighting, if nec.
; Not all possible cases are handled (window resizing, for example), but
; the most common ones are.
public _myRectFill
public _myScrollRaster
public _myCloseWindow
public _oldRectFill
public _oldScrollRaster
public _oldCloseWindow
_myRectFill: ; pardon me
move.l a4,-(sp)
jsr _geta4 ; establish addressing
tst.w _snip
beq.s 1$ ; no highlighted area; get out
cmpa.l _sniprp,a1
bne.s 1$ ; not the same RastPort; get out
movem.l a1/d0-d5,-(sp)
jsr _clearHi ; de-highlight
movem.l (sp)+,a1/d0-d5
1$: movea.l _oldRectFill,a0
movea.l (sp)+,a4
jmp (a0) ; continue into library
_myScrollRaster: ; 'scuse
move.l a4,-(sp)
jsr _geta4
tst.w _snip
beq.s 1$
cmpa.l _sniprp,a1
bne.s 1$
movem.l a1/d0-d5,-(sp)
jsr _clearHi
movem.l (sp)+,a1/d0-d5
1$: movea.l _oldScrollRaster,a0
movea.l (sp)+,a4
jmp (a0)
_myCloseWindow:
move.l a4,-(sp)
jsr _geta4
tst.w _snip
beq.s 1$
cmpa.l _snipw,a0
bne.s 1$ ; not the same Window; get out
clr.w _snip
clr.l _capttf ; Window closing; reset indicators
1$: movea.l _oldCloseWindow,a1
movea.l (sp)+,a4
jmp (a1)
;************************
; input event stream glue
public _handlerCode
_handlerCode:
movem.l d2/d3/a0/a1/a4/a6,-(sp) ; i think this is right
jsr _geta4
jsr _myHandler
movem.l (sp)+,d2/d3/a0/a1/a4/a6
rts
#endasm
/*********************************************/
/* SnipIt's input event handler */
struct InputEvent *myHandler(d2, d3, ev)
long d2, d3;
register struct InputEvent *ev;
{
register struct InputEvent *inev, **evp;
struct InputEvent *outev;
if (jobFlag)
return ev;
inev = ev;
outev = NULL;
/* back-pointer */
evp = &outev;
/*
* Loop thru the possibly linked list of events.
* We remove the ones having meaning to SnipIt, and leave the others
*/
while (inev) {
ev = inev;
inev = ev->ie_NextEvent;
/* ensure that main code isn't running and this is a mouse event */
if (ev->ie_Class == IECLASS_RAWMOUSE)
ev = doEvent(ev);
/* patch back-pointer */
if (*evp = ev)
evp = &ev->ie_NextEvent;
}
/* pass 'em along */
return outev;
}
/*********************************************/
/* handle a single (mouse) input event */
struct InputEvent *doEvent(ev)
register struct InputEvent *ev;
{
static int lflag, rflag, cmd;
register UWORD code;
register int x, y;
x = ev->ie_X;
y = ev->ie_Y;
code = ev->ie_Code;
/* in mid-snip? */
if (lflag && code == IECODE_NOBUTTON &&
(ev->ie_Qualifier & IEQUALIFIER_LEFTBUTTON)) {
mouse(M_MOVE, x, y);
return ev;
}
/* button transition event... */
code &= ~IECODE_UP_PREFIX;
/* mouse button down event? */
if ((ev->ie_Code & IECODE_UP_PREFIX) == 0) {
if (cmd = ev->ie_Qualifier & (cmd1 | cmd2)) {
if (!rflag && code == IECODE_LBUTTON) {
lflag++;
mouse(M_DOWN, x, y);
}
else if (!lflag && code == IECODE_RBUTTON)
rflag++; /* note transition */
return NULL;
}
}
/* release of left mouse button? */
else if (lflag && code == IECODE_LBUTTON) {
lflag = 0;
mouse(M_UP, x, y);
return NULL;
}
/* release of right mouse button? */
else if (rflag && code == IECODE_RBUTTON) {
rflag = 0;
/* kick main code */
jobFlag = cmd;
Signal(myTask, 1L << mySignal);
return NULL;
}
/* event back into stream */
return ev;
}
/*********************************************/
/* find a console containing the layer holding (x,y); return success flag */
int whichConsole(layer, x, y)
struct Layer *layer;
int x, y;
{
register struct ConUnit *cu, *rcu;
register struct Node *node;
/* result conunit */
rcu = NULL;
_Forbid();
/* begin at the beginning */
node = ConsoleBase->conUnits.lh_Head;
/* next is NULL when back at listhead */
while (node->ln_Succ) {
cu = (struct ConUnit *) node;
/* see if console window's layer is the same */
if (cu && cu->cu_Window && cu->cu_Window->RPort->Layer == layer) {
rcu = cu; /* found it */
break;
}
node = node->ln_Succ;
}
Permit();
if (rcu) {
snip = CON_SNIP;
snipw = rcu->cu_Window;
sniprp = snipw->RPort;
charx = rcu->cu_XRSize;
chary = rcu->cu_YRSize;
origx = rcu->cu_XROrigin;
origy = rcu->cu_YROrigin;
maxx = rcu->cu_XMax;
maxy = rcu->cu_YMax;
}
return rcu != NULL;
}
/*********************************************/
/* find a window containing the layer holding (x,y); return success flag */
int whichWindow(s, layer, x, y)
struct Screen *s;
struct Layer *layer;
int x, y;
{
register struct Window *w, *rw;
if (!windows)
return NULL;
/* result window */
rw = NULL;
_Forbid();
w = s->FirstWindow;
while (w) {
if (w->WLayer == layer) {
rw = w;
break;
}
w = w->NextWindow;
}
Permit();
if (rw) {
snip = WIN_SNIP;
snipw = rw;
sniprp = snipw->RPort;
charx = sniprp->Font->tf_XSize;
chary = sniprp->Font->tf_YSize;
origx = rw->BorderLeft;
origy = rw->BorderTop;
maxx = (rw->Width - rw->BorderRight - origx) / charx - 1;
maxy = (rw->Height - rw->BorderBottom - origy) / chary - 1;
}
return rw != NULL;
}
/*********************************************/
/* handle meaningful mouse activity */
mouse(event, mx, my)
int event;
register int mx, my;
{
static struct Screen *s;
static struct Layer *layer;
if (event == M_DOWN)
s = IntuitionBase->FirstScreen;
/* correct raw positions according to this screen */
if (!(s->ViewPort.Modes & LACE))
my /= 2;
mx += s->MouseX - 2; /* accumulate deltas */
my += s->MouseY - 1; /* x,y adjusted for feel */
if (event == M_DOWN) {
/* de-hilight, if nec. */
if (snip)
hiSnip(0);
/* turn flag off */
snip = 0;
/* locate pointed-at layer */
if ((layer = WhichLayer(&s->LayerInfo, (long) mx, (long) my)) &&
(whichConsole(layer, mx, my) || whichWindow(s, layer, mx, my))) {
/* if mouse down in title line area, remain clear */
if (my - snipw->TopEdge < origy)
snip = 0;
}
}
/* nothing interesting */
if (!snip)
return;
/* mouse to window-relative cell coordinates */
mx = (mx - snipw->LeftEdge - origx) / charx;
if (mx < 0)
mx = 0;
else if (maxx < mx)
mx = maxx;
my = (my - snipw->TopEdge - origy) / chary;
if (my < 0)
my = 0;
else if (maxy < my)
my = maxy;
/* highlighting games ahead */
if (event == M_DOWN) {
state = M_DOWN;
if (lock_layer)
LockLayerRom(layer);
snipx[0] = mx;
snipy[0] = my;
hiLite(mx, my, 1, 1);
}
else if (event == M_UP) {
snipx[1] = mx;
snipy[1] = my;
if (state == M_MOVE)
hiLite(lastx, lasty, 1, 1);
hiLite(snipx[0], snipy[0], 1, 1);
hiSnip(charx == 8);
state = M_UP;
if (charx != 8) /* only able to do 8 pixel wide fonts */
clearHi();
if (lock_layer)
UnlockLayerRom(layer);
}
else if (mx != lastx || my != lasty) {
if (state == M_MOVE)
hiLite(lastx, lasty, 1, 1);
hiLite(lastx = mx, lasty = my, 1, 1);
state = M_MOVE;
}
}
/*********************************************/
/* de-highlight; snip is known to be set */
clearHi()
{
if (state == M_UP)
hiSnip(0);
else if (lock_layer)
return;
else {
hiLite(snipx[0], snipy[0], 1, 1);
if (state == M_MOVE)
hiLite(lastx, lasty, 1, 1);
}
snip = 0;
}
/*********************************************/
/* local cleanup for this module */
finiHand()
{
int i;
PLANEPTR p;
if (snip)
clearHi();
if (p = captbm.Planes[0])
FreeRaster(p, (long) captx, (long) capty);
}
/*********************************************/
/* manufacture rastport with bitmap, ready to receive captured bitmap */
int allocMap(sx, sy)
int sx, sy;
{
PLANEPTR p;
/* release previous, if any */
if (p = captbm.Planes[0]) {
FreeRaster(p, (long) captx, (long) capty);
captbm.Planes[0] = NULL;
}
/* record new map size */
captx = sx;
capty = sy;
/* build new bitmap to contain snipped area */
InitBitMap(&captbm, 1L, (long) captx, (long) capty);
InitRastPort(&captrp);
captrp.BitMap = &captbm;
/* allocate bitmap planes */
p = (PLANEPTR) AllocRaster((long) captx, (long) capty);
if (!p)
return 0;
captbm.Planes[0] = p;
return 1;
}
/*********************************************/
/* video reverse the capture area; perform capture if flagged */
hiSnip(capt)
int capt;
{
register int px, py, qx, qy, tx, ty;
long ox, oy;
/* need these vars to be handy */
tx = maxx;
/* take care of backward snip areas */
if (snipy[0] < snipy[1] ||
snipy[0] == snipy[1] && snipx[0] <= snipx[1]) {
px = snipx[0];
py = snipy[0];
qx = snipx[1];
qy = snipy[1];
}
else {
px = snipx[1];
py = snipy[1];
qx = snipx[0];
qy = snipy[0];
}
/* only if capturing more than 1 cell... */
if (capt && (px != qx || py != qy)) {
/* left and right sides */
left = px;
right = qx;
/* get a new bitmap */
if (allocMap((tx + 1) * charx, (qy - py + 1) * chary)) {
/* copy console contents into snip-map */
ox = origx;
oy = origy + py * chary;
if (snip == CON_SNIP) { /* user-specified corrections */
ox += con_offx;
oy += con_offy;
}
else {
ox += win_offx;
oy += win_offy;
}
ClipBlit(sniprp, ox, oy, &captrp, 0L, 0L,
(long) captx, (long) capty, 0xC0L);
/* note new info in snip-map */
capttf = sniprp->Font;
}
else {
/* no memory, act dumb */
snip = captx = capty = 0;
return;
}
}
/* perform hilighting */
while (py <= qy) {
if (py == qy)
tx = qx;
hiLite(px, py, tx - px + 1, 1);
px = 0;
py++;
}
}
/*********************************************/
/* low-lever video reverser */
hiLite(x, y, xs, ys)
int x, y, xs, ys;
{
register long ox, oy;
ox = origx + x * charx;
oy = origy + y * chary;
if (snip == CON_SNIP) { /* user-specified corrections */
ox += con_offx;
oy += con_offy;
}
else {
ox += win_offx;
oy += win_offy;
}
ClipBlit(sniprp, ox, oy, sniprp, ox, oy,
(long) (xs * charx), (long) (ys * chary), 0x50L);
}
/*********************************************/
SHAR_EOF
cat << \SHAR_EOF > main.c
/* :ts=4
*
* Amiga SnipIt 1.2
* (c) (opyright 1987,1988 - Scott Evernden - All Rights Reserved
*
* main.c - cutter/paster like SunTools
*
* Permission is granted to modify and redistribute as long
* as this notice is left intact.
*
*/
/**********************
The strategy here begins with the installation of some input handler
code into the input event handler chain. This code looks for mouse
actions and keyboard presses that indicate that text is being snipped,
or is being pasted.
Snipped text (plane 0) is always immediately copied into a temp 1-plane
bitmap without further processing. Subsequents "snips" cause the old
snipped bitmap to be thrown away, and a new one captured.
Pasting requires that the text in the capture bitmap be recognized.
This is not done in the input handler code, since it would cause all
pending input events to pile up while the recognizer is running.
Instead, the input handler code signals the main snipit code (RUNning
in the background, itself) to do the recognition and fake the kb events.
During this period, the input handler code temporarily suspends its
special processing waiting for the main code (recognizer) to finish.
Once a capture bitmap has been recognized and converted into a sequence
of key codes, it is deallocated, and subsequent pastes don't require
the recognition step.
**********************/
#include "hs.h"
struct Task *_FindTask();
struct Library *_OpenLibrary();
BPTR output = 0;
long LayersBase; /* for WhichLayer() */
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
struct ConsoleBase *ConsoleBase; /* defined in hs.h */
/* communication with input.device */
struct IOStdReq *inpReq;
struct MsgPort *inpPort;
/* communication with console.device */
struct MsgPort *conPort;
struct IOStdReq *conReq;
/* who I am */
struct Task *myTask;
/* snipit's port */
struct MsgPort *myPort;
struct MyMessage {
struct Message m;
int done, huh, off;
int w_offx, w_offy;
int c_offx, c_offy;
long alen;
char *aptr;
} myMsg, *msgp;
/* for snipit's input handler */
struct Interrupt handler;
/* flags handler installation for cleanup */
int handlerIn;
/* snipit's allocated signal bit */
int mySignal = -1L;
/* snipit's input handler code */
VOID handlerCode();
/* snipit replacement functions */
VOID myRectFill(), myScrollRaster(), myCloseWindow();
/* remember original library vectors */
long oldRectFill, oldScrollRaster, oldCloseWindow;
/* vector offsets of certain functions */
extern int lvoRectFill, lvoScrollRaster, lvoCloseWindow;
/* detach stuff */
long running = 0;
char *_procname = "\x9B33mSnipIt 1.2\x9B0m";
char *huh_msg = "Huh? (for help type: snipit h)";
/* "Can't open"... forms */
char *i_libname = "~intuition.library";
char *g_libname = "~graphics.library";
char *l_libname = "~layers.library";
char *i_devname = "~input.device";
char *c_devname = "~console.device";
char *port_name = "^\x9B33mSnipIt 1.2\x9B0m Port";
long _savsp;
extern int jobFlag;
extern int con_offx, con_offy;
extern int win_offx, win_offy;
extern int cmd1, cmd2;
extern int snip, lock_layer, windows;
extern char preString[];
/*********************************************/
/* pick up the ABS symbols describing gfx/intui lib offsets
*/
#asm
dseg
public _LVORectFill
public _LVOScrollRaster
public _LVOCloseWindow
_lvoRectFill dc.w _LVORectFill
_lvoScrollRaster dc.w _LVOScrollRaster
_lvoCloseWindow dc.w _LVOCloseWindow
cseg
#endasm
/*********************************************/
writes(str)
register char *str;
{
register char *piece;
register long len;
len = 0;
if (*str == '!') {
piece = "Can't ";
len = 6;
}
else if (*str == '~') {
piece = "Can't open ";
len = 11;
}
else if (*str == '^') {
piece = "Can't create ";
len = 13;
}
else if (*str == '_') {
piece = _procname;
len = 17;
}
if (len) {
str++;
_Write(output, piece, len);
}
/* output a message & newline */
_Write(output, str, (long) strlen(str));
_Write(output, "\n", 1L);
}
/*********************************************/
fini()
{
long stat;
/* cleanup in other modules */
finiHand();
finiReco();
/* restore gfx/intui library vectors */
if (oldRectFill)
SetFunction(GfxBase, (long) lvoRectFill, oldRectFill);
if (oldScrollRaster)
SetFunction(GfxBase, (long) lvoScrollRaster, oldScrollRaster);
if (oldCloseWindow)
SetFunction(IntuitionBase, (long) lvoCloseWindow, oldCloseWindow);
/* remove snipit input handler */
if (handlerIn) {
inpReq->io_Command = IND_REMHANDLER;
inpReq->io_Data = (APTR) &handler;
DoIO(inpReq);
}
/* close down console.device */
if (conReq) {
if (conReq->io_Device)
CloseDevice(conReq);
DeleteStdIO(conReq);
}
if (conPort)
DeletePort(conPort);
/* close down input.device */
if (inpReq) {
if (inpReq->io_Device)
CloseDevice(inpReq);
DeleteStdIO(inpReq);
}
if (inpPort)
DeletePort(inpPort);
/* release snipit's port & signal bit */
if (myPort)
DeletePort(myPort);
if (mySignal != -1)
FreeSignal(1L << mySignal);
/* close libraries */
if (GfxBase)
_CloseLibrary(GfxBase);
if (LayersBase)
_CloseLibrary(LayersBase);
if (IntuitionBase)
_CloseLibrary(IntuitionBase);
if (output)
_Close(output);
#asm
moveq #0,d0 ;pick up return exit code
move.l __savsp,sp ;get back original stack pointer
rts ;and exit
#endasm
}
/*********************************************/
int init()
{
long stat;
/* global record of this task's ID */
myTask = _FindTask((char *) NULL);
/* need intuitionbase to read mouse pos. & screen layer */
IntuitionBase = (struct IntuitionBase *) _OpenLibrary(i_libname + 1, 0L);
if (IntuitionBase == NULL) {
writes(i_libname);
return 0;
}
/* need graphics since we do */
GfxBase = (struct GfxBase *) _OpenLibrary(g_libname + 1, 0L);
if (GfxBase == NULL) {
writes(g_libname);
return 0;
}
/* layers for WhichLayer() */
LayersBase = (long) _OpenLibrary(l_libname + 1, 0L);
if (LayersBase == NULL) {
writes(l_libname);
return 0;
}
/* signal from input event handler to main code */
mySignal = AllocSignal(-1L);
if (mySignal == -1) {
writes("!allocate a signal bit.");
return 0;
}
/* a signal to this port will terminate us */
myPort = CreatePort(port_name + 1, 0L);
if (myPort == NULL) {
writes(port_name);
return 0;
}
/* port to the input.device */
inpPort = CreatePort((char *) NULL, 0L);
if (inpPort == NULL) {
writes("^input.device port.");
return 0;
}
/* need an i/o request */
inpReq = CreateStdIO(inpPort);
if (inpReq == NULL) {
writes("^input.device i/o request.");
return 0;
}
/* open input.device */
stat = OpenDevice(i_devname + 1, 0L, inpReq, 0L);
if (stat != 0) {
writes(i_devname);
return 0;
}
/* port to the console.device */
conPort = CreatePort((char *) NULL, 0L);
if (!conPort) {
writes("^console.device port.");
return 0;
}
/* need an i/o request */
conReq = CreateStdIO(conPort);
if (!conReq) {
writes("^console.device i/o request.");
return 0;
}
/* open console.device */
stat = OpenDevice(c_devname + 1, -1L, conReq, 0L);
if (stat != 0) {
writes(c_devname);
return 0;
}
/* check for consolebase */
ConsoleBase = (struct ConsoleBase *) conReq->io_Device;
if (!ConsoleBase) {
writes("!find ConsoleBase.");
return 0;
}
/* handler command stuff */
handler.is_Code = handlerCode;
handler.is_Node.ln_Pri = 51;
/* install new input event handler */
inpReq->io_Command = IND_ADDHANDLER;
inpReq->io_Data = (APTR) &handler;
stat = DoIO(inpReq);
if (stat != 0) {
writes("ADDHANDLER request failed.");
return 0;
}
handlerIn = 1;
/* function catchers */
oldRectFill = SetFunction(GfxBase, (long) lvoRectFill, myRectFill);
if (oldRectFill == 0) {
writes("!replace RectFill()");
return 0;
}
oldScrollRaster = SetFunction(GfxBase, (long) lvoScrollRaster,
myScrollRaster);
if (oldScrollRaster == 0) {
writes("!replace ScrollRaster()");
return 0;
}
oldCloseWindow = SetFunction(IntuitionBase, (long) lvoCloseWindow,
myCloseWindow);
if (oldCloseWindow == 0) {
writes("!replace CloseWindow()");
return 0;
}
return 1;
}
/*********************************************/
int jump(mode)
int mode;
{
char ch;
while (0 < msgp->alen--) {
ch = *msgp->aptr++;
if ((ch != ' ' && ch != '\t' && ch != '\n') == mode)
return ch;
}
return 0;
}
/*********************************************/
int innum(base)
int base;
{
int result, neg, ch;
result = 0;
ch = jump(1);
if (!ch)
return 0;
neg = ch == '-';
if ((neg || ch == '+') && 0 < msgp->alen--)
ch = *msgp->aptr++;
while (1) {
ch -= '0';
if (9 < ch)
ch -= 7; /* was 'A'-'F' */
if (15 < ch)
ch -= 32; /* was 'a'-'f' */
if (ch < 0 || base <= ch) {
msgp->alen++; /* ungetc */
msgp->aptr--;
break;
}
result = result * base + ch;
if (msgp->alen-- <= 0)
break;
ch = *msgp->aptr++;
}
return neg ? -result : result;
}
/*********************************************/
usage()
{
writes("Usage: snipit [opts]");
writes("where opts can be any of:");
writes(" ? or h Help; this text");
writes(" q Quit; remove SnipIt from the system");
writes(" p \"prestring\" When pasting using Command-B key, insert");
writes(" \"prestring\" before each line. In quotes");
writes(" l 1 or 0 Lock layer (or don't) while snipping");
writes(" u +/-number Adjust cell x position in console windows");
writes(" v +/-number Adjust cell y position in console windows");
writes(" x +/-number Adjust cell x position in non-console windows");
writes(" y +/-number Adjust cell y position in non-console windows");
writes(" a hex-number Qualifier for Command-A key (default LEFT-AMIGA)");
writes(" b hex-number Qualifier for Command-B key (default LEFT-ALT)");
writes("");
writes("Defaults are: p\"> \" l0 u0 v0 x0 y0 a0040 b0010");
}
/*********************************************/
int options()
{
char *cp;
int temp, ch;
msgp->done = msgp->huh = msgp->off = 0;
do {
/* locate a char after whitespace */
ch = jump(1); /* advance to 1st non-white */
if ('A' <= ch && ch <= 'Z')
ch = ch - 'A' + 'a'; /* tolower */
/* act on char */
switch (ch) {
case 0: break;
case 'q': msgp->done = 1;
return 0; /* die */
case 'p': cp = preString;
ch = jump(1); /* delim char */
if (ch) {
while (0 < msgp->alen-- &&
(*cp = *msgp->aptr++) != ch) {
cp++;
if (preString + PRE_SIZE <= cp)
break;
}
}
*cp = 0;
break;
case 'x': if (snip == WIN_SNIP)
clearHi();
msgp->off = 1;
win_offx += innum(10);
break;
case 'y': if (snip == WIN_SNIP)
clearHi();
msgp->off = 1;
win_offy += innum(10);
break;
case 'u': if (snip == CON_SNIP)
clearHi();
msgp->off = 1;
con_offx += innum(10);
break;
case 'v': if (snip == CON_SNIP)
clearHi();
msgp->off = 1;
con_offy += innum(10);
break;
case 'a': if (temp = innum(16));
cmd1 = temp;
break;
case 'b': if (temp = innum(16));
cmd2 = temp;
break;
case 'l': ch = jump(1); /* first char */
if (ch)
lock_layer = ch == '1';
break;
case 'w': ch = jump(1); /* first char */
if (ch)
windows = ch == '1';
break;
default: msgp->huh = 1; /* newline, too - end of string */
break;
}
} while (jump(0)); /* advance to whitespace */
if (msgp->off) {
win_offx = win_offx < -32 ? -32 : 32 < win_offx ? 32 : win_offx;
win_offy = win_offy < -32 ? -32 : 32 < win_offy ? 32 : win_offy;
con_offx = con_offx < -32 ? -32 : 32 < con_offx ? 32 : con_offx;
con_offy = con_offy < -32 ? -32 : 32 < con_offy ? 32 : con_offy;
msgp->w_offx = win_offx;
msgp->w_offy = win_offy;
msgp->c_offx = con_offx;
msgp->c_offy = con_offy;
}
return 1; /* i.e., keep running */
}
/*********************************************/
outnum(n)
int n;
{
char d;
if (n < 0) {
n = -n;
_Write(output, "-", 1L);
}
if (n > 9) {
d = n / 10 + '0';
_Write(output, &d, 1L);
}
d = n % 10 + '0';
_Write(output, &d, 1L);
}
/*********************************************/
currAdjust(type, x, y)
char *type;
int x, y;
{
_Write(output, type, 7L);
_Write(output, " adjustment now: x=", 19L);
outnum(x);
_Write(output, ",y=", 3L);
outnum(y);
_Write(output, "\n", 1L);
}
/*********************************************/
checkStatus()
{
if (myMsg.huh)
writes(huh_msg);
else if (myMsg.done)
writes("_ cancelled.");
else if (myMsg.off) {
currAdjust("Console", myMsg.c_offx, myMsg.c_offy);
currAdjust("Window ", myMsg.w_offx, myMsg.w_offy);
}
}
/*********************************************/
_main(alen, aptr) /* DOSBase and ExecBase opened already by crt0.o */
long alen;
char *aptr;
{
static int pass;
int keep_going;
long sige, sigt;
struct MsgPort *port, *rport;
/* sever seglists */
do_detach(&alen, &aptr);
myMsg.alen = alen;
myMsg.aptr = aptr;
/* help requested?? */
if (*aptr == '?' || *aptr == 'h')
usage();
/* installed already? if so, pass arguments */
else if (port = FindPort(port_name + 1)) {
if (alen <= 1)
writes("_ already installed!");
else {
myMsg.m.mn_ReplyPort = rport = CreatePort(NULL, 0L);
if (!rport)
writes("^a port");
else {
PutMsg(port, &myMsg);
_WaitPort(rport); /* wait for reply */
_GetMsg(rport);
DeletePort(rport);
/* check return stats */
checkStatus();
}
}
}
/* install & deal with args */
else if (init()) {
msgp = &myMsg;
if (options() && !myMsg.huh) {
writes("_ installed. \xA9 1988 - Scott Evernden");
running = 1;
/* signals which mean something */
sige = 1L << mySignal; /* request for recognition */
sigt = 1L << myPort->mp_SigBit; /* options message */
/* process requests for handler code
* while awaiting options signal
*/
keep_going = 1;
while (keep_going) {
if (Wait(sige | sigt) == sige) {
buildEvents();
jobFlag = 0; /* lower active flag */
}
else while (msgp = (struct MyMessage *) GetMsg(myPort)) {
keep_going = options();
_ReplyMsg(msgp);
}
}
}
else {
if (myMsg.huh)
writes(huh_msg);
writes("_ not installed.");
}
}
running = 1;
/* terminate */
Delay(10L);
fini();
}
SHAR_EOF
cat << \SHAR_EOF > patch.c
/* "Patch" fix SnipIt to use a different keymap */
/* 9/1/88 - Scott Evernden */
#include <stdio.h>
#include <ctype.h>
FILE *infile, *datafile;
/* original keycode table starts like this... */
unsigned char match[] = {
0x40, 0x81, 0xAA, 0x83, 0x84, 0x85, 0x87, 0x2A,
0x89, 0x8A, 0x88, 0x8C, 0x38, 0x0B, 0x39, 0x3A,
0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0
};
main()
{
long pos, ftell();
unsigned char *mp;
int ch, i;
/* gonna write into this file */
infile = fopen("SnipIt", "r+");
if (!infile) {
puts("Can't open \"SnipIt\"");
exit(0);
}
/8 need to read this one */
datafile = fopen("SnipIt.keys", "r");
if (!datafile) {
puts("Can't open \"SnipIt.keys\"");
exit(0);
}
/* locate original table */
mp = match;
while (*mp && (ch = fgetc(infile)) != EOF) {
if (ch != *mp)
mp = match;
else if (mp++ == match)
pos = ftell(infile) - 1;
}
if (ch == EOF) {
puts("Are you sure this is an original copy of \"SnipIt\"?");
fclose(infile);
fclose(datafile);
exit(0);
}
fputs("Patching keytable...", stdout);
fseek(infile, pos, 0L);
for (i = 32; i < 127; i++)
fputc(innum() & 0xFF, infile);
fclose(infile);
fclose(datafile);
puts("done");
}
innum()
{
int result;
int ch;
do {
ch = fgetc(datafile);
} while (!isxdigit(ch));
if (ch == EOF)
return 0;
result = 0;
do {
ch -= '0';
if (9 < ch)
ch -= 7;
if (15 < ch)
ch -= 32;
result = result * 16 + ch;
ch = fgetc(datafile);
} while (isxdigit(ch));
return result;
}
SHAR_EOF
cat << \SHAR_EOF > reco.c
/* :ts=4
*
* Amiga SnipIt 1.2
* (c) (opyright 1987,1988 - Scott Evernden - All Rights Reserved
*
* reco.c - recognize & construct char code input
*
*/
#include "hs.h"
char *_AllocMem();
/* ascii to keycode (this is a hack; is there a correct way to do this?) */
char table[] = {
/* ! " # $ % & ' */
/* ( ) * + , - . / */
/* 0 1 2 3 4 5 6 7 */
/* 8 9 : ; < = > ? */
/* @ A B C D E F G */
/* H I J K L M N O */
/* P Q R S T U V W */
/* X Y Z [ \ ] ^ _ */
/* ` a b c d e f g */
/* h i j k l m n o */
/* p q r s t u v w */
/* x y z { | } ~ */
0x40, 0x81, 0xAA, 0x83, 0x84, 0x85, 0x87, 0x2A,
0x89, 0x8A, 0x88, 0x8C, 0x38, 0x0B, 0x39, 0x3A,
0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0xA9, 0x29, 0xB8, 0x0C, 0xB9, 0xBA,
0x82, 0xA0, 0xB5, 0xB3, 0xA2, 0x92, 0xA3, 0xA4,
0xA5, 0x97, 0xA6, 0xA7, 0xA8, 0xB7, 0xB6, 0x98,
0x99, 0x90, 0x93, 0xA1, 0x94, 0x96, 0xB4, 0x91,
0xB2, 0x95, 0xB1, 0x1A, 0x0D, 0x1B, 0x86, 0x8B,
0x00, 0x20, 0x35, 0x33, 0x22, 0x12, 0x23, 0x24,
0x25, 0x17, 0x26, 0x27, 0x28, 0x37, 0x36, 0x18,
0x19, 0x10, 0x13, 0x21, 0x14, 0x16, 0x34, 0x11,
0x32, 0x15, 0x31, 0x9A, 0x8D, 0x9B, 0x80
};
static struct InputEvent event;
char *evs, *evp;
char preString[PRE_SIZE + 1] = "> "; /* a prestring */
int evslen;
extern struct IOStdReq *inpReq;
extern struct TextFont *capttf;
extern struct BitMap captbm;
extern int captx, capty;
extern int charx, chary;
extern int left, right;
extern int cmd1, cmd2, jobFlag;
/*********************************************/
/* cleanup, local to this module */
finiReco()
{
/* event string is allocated */
if (evs)
_FreeMem(evs, (long) evslen);
}
/*********************************************/
/* entry to recognizer; generates keycode events from the capture bitmap */
buildEvents()
{
register char *cp;
PLANEPTR p;
int code;
/* prepare request to input device */
inpReq->io_Command = IND_WRITEEVENT;
inpReq->io_Flags = 0;
inpReq->io_Length = sizeof (struct InputEvent);
inpReq->io_Data = (APTR) &event;
/* new snip-map? */
if (capttf) {
/* new buffer for keycodes */
if (evs)
_FreeMem(evs, (long) evslen);
evslen = (captx / charx) * (capty / chary);
evs = (char *) _AllocMem((long) evslen, 0L);
if (evp = evs)
buildCodes();
capttf = NULL; /* reset "newly-captured" indicator */
/* reco'ed, so drop the bitmap */
if (p = captbm.Planes[0]) {
FreeRaster(p, (long) captx, (long) capty);
captbm.Planes[0] = NULL;
}
}
else if (evp = evs) {
while (*evp != -1) {
if (jobFlag & cmd2) {
cp = preString;
while (*cp)
sendKey(*cp++);
}
do
sendKey(code = *evp++);
while (code != '\n' && *evp != -1);
}
}
}
/*********************************************/
/* inject a (fake) keyboard press/release into the input stream */
sendKey(code)
int code;
{
/* convert to raw key */
code = code == '\n' ? 0x44 : table[code - 32];
/* build key down event */
event.ie_Class = IECLASS_RAWKEY;
event.ie_Code = code & 0x7F;
event.ie_Qualifier = IEQUALIFIER_RELATIVEMOUSE;
if (code & 0x80)
event.ie_Qualifier |= IEQUALIFIER_LSHIFT;
event.ie_NextEvent = NULL;
/* make it happen */
DoIO(inpReq);
/* build key up event (req'd?) */
event.ie_Class = IECLASS_RAWKEY;
event.ie_Code = (code & 0x7F) | IECODE_UP_PREFIX;
event.ie_Qualifier = IEQUALIFIER_RELATIVEMOUSE;
if (code & 0x80)
event.ie_Qualifier |= IEQUALIFIER_LSHIFT;
event.ie_NextEvent = NULL;
/* make it happen */
DoIO(inpReq);
}
/*********************************************/
/* actually makes the keycodes */
buildCodes()
{
register int code, px, py, wid, lastx, lasty, spaces;
char *cp;
/* heuristics for text structure (i.e., newlines) */
px = left;
py = 0;
lastx = captx / charx - 1;
lasty = capty / chary - 1;
wid = lastx;
while (py <= lasty) {
/* prestring on cmd2 key */
if (jobFlag & cmd2) {
cp = preString;
while (*cp)
sendKey(*cp++); /* don't record */
}
/* on the last line? */
if (py == lasty)
lastx = right;
/* for each cell... */
while (px <= lastx) {
/* recognize single character */
code = reco(px++, py);
/* we're gonna count runs of spaces */
spaces = 0;
while (code == ' ' && px <= wid) {
spaces++;
code = reco(px++, py);
}
/* send / record, if no spaces */
if (!spaces)
sendKey(*evp++ = code);
/* if end of line is all spaces, then regard as newline */
else if (code == ' ' && wid < px)
sendKey(*evp++ = '\n');
/* if more text on line after snip area, then not a newline */
else if (py < lasty || px <= lastx + 1) {
while (spaces--)
sendKey(*evp++ = ' ');
sendKey(*evp++ = code);
}
/* emit spaces */
else {
spaces -= px - lastx - 2;
while (spaces--)
sendKey(*evp++ = ' ');
}
}
/* next is leftside of next row down */
px = 0;
py++;
}
*evp = -1; /* record terminator */
}
/*********************************************/
/* return ascii code of character in capture bitmap at (x,y) */
int reco(x, y)
int x, y;
{
register char *s, *d, *sp, *dp;
register int hyt, i;
/* recognize cell at (x,y) */
sp = (char *) capttf->tf_CharData;
dp = (char *) captbm.Planes[0] + y * chary * captbm.BytesPerRow + x;
for (i = 32; i < 128; sp++, i++) {
s = sp;
d = dp;
hyt = capttf->tf_YSize;
if (*s == *d) {
do {
if (--hyt == 0)
return i;
s += capttf->tf_Modulo;
d += captbm.BytesPerRow;
} while (*s == *d);
}
else if (*s == ~*d) {
do {
if (--hyt == 0)
return i;
s += capttf->tf_Modulo;
d += captbm.BytesPerRow;
} while (*s == ~*d);
}
}
return '?'; /* unknown */
}
SHAR_EOF
cat << \SHAR_EOF > snipit.keys
40 81 AA 83 84 85 87 2A
89 8A 88 8C 38 0B 39 3A
0A 01 02 03 04 05 06 07
08 09 A9 29 B8 0C B9 BA
82 A0 B5 B3 A2 92 A3 A4
A5 97 A6 A7 A8 B7 B6 98
99 90 93 A1 94 96 B4 91
B2 95 B1 1A 0D 1B 86 8B
00 20 35 33 22 12 23 24
25 17 26 27 28 37 36 18
19 10 13 21 14 16 34 11
32 15 31 9A 8D 9B 80
SHAR_EOF
cat << \SHAR_EOF > patch.doc
KeyMap patcher:
==============
The program "patch" will "fix" SnipIt to work with foreign, custom, and the
Dvorak keymaps. This measure is a stopgap "bandaid" (i.e., hack) until a
more appropriate handling of KeyMaps is employed by SnipIt.
Make sure that (a copy of) "snipit" and a file named "snipit.keys" are in
the 'current directory'. Simply incant:
> patch
and SnipIt will be modified according to the data in the "snipit.keys" file.
The file "snipit.keys" has a format like the following (this example is
the default- for the 'usa0' keymap):
40 81 AA 83 84 85 87 2A
89 8A 88 8C 38 0B 39 3A
0A 01 02 03 04 05 06 07
08 09 A9 29 B8 0C B9 BA
82 A0 B5 B3 A2 92 A3 A4
A5 97 A6 A7 A8 B7 B6 98
99 90 93 A1 94 96 B4 91
B2 95 B1 1A 0D 1B 86 8B
00 20 35 33 22 12 23 24
25 17 26 27 28 37 36 18
19 10 13 21 14 16 34 11
32 15 31 9A 8D 9B 80
It should be a list of 95 hexadecimal numbers, each corresponding to the
ASCII codes 32-126 (95 codes- ' ' thru '~'). The hex number is the I.D.
of the keyboard key (as revealed in the Appendix to the AmigaDOS Technical
Manual and other sources). If the keyboard key must be "shifted" in order
to achieve the corresponding ASCII code, then the hex keycode number is
"OR"ed with an 0x80 (high bit on).
The patch program simply searches the SnipIt program file looking for the
original hardwired table, and then overwrites the 95 code values.
Consequently, you need to run "patch" on the original copy of SnipIt.
-scott
SHAR_EOF
cat << \SHAR_EOF > snipit.doc
SnipIt 1.2 - Copyright (c) 1988 - Scott Evernden, All Rights Reserved
What is SnipIt?
================
SnipIt is a CLI program which allows you to copy text directly from the
Amiga screen in any window, and then paste it into any other place, as
though you had typed that text at the keyboard. You mark the text you
want to 'snip' using the mouse. You also use the mouse to 'paste' the
last snipped text into the active window, requester, or anywhere.
SnipIt is a program which installs itself into the input stream handling
code of AmigaDOS. It waits for you to hold down the LEFT-AMIGA (or
optionally another key) while using the mouse.
Running the Program
===================
This program will only run properly from the CLI. You start it like
> snipit
at which point, SnipIt will install itself, and print a message.
You can control certain operations and modes of SnipIt when you first
install it and later while it is running. You do this by typing
"snipit" with 'option' letters and possible arguments. For example, you
can tell SnipIt to stop running:
> snipit q
In other words, type "snipit" followed by a "q" for 'quit'. Other
options to control SnipIt's behavior will be described below.
Marking Text to be Copied
=========================
To mark text to be copied, simply depress the LEFT-AMIGA key (by
default), move the mouse pointer to a position in any window containing
text and hold down the LEFT mouse button. While holding down the LEFT
mouse button you move the mouse to the opposite end of the text area you
want to copy and then release. As you do this, SnipIt will mark
(hilight) both ends of the area you are designating.
Once you have released the LEFT mouse button, SnipIt will fully
highlight and 'snapshot' the text within the area you have marked out.
Pasting the Copied Text
=======================
You can deposit the text you copied by, again, holding down the
LEFT-AMIGA key, and clicking the RIGHT mouse button.
SnipIt will inject keystroke codes into the input stream, so you can
paste text into any active window, requester, or anything else which is
expecting keyboard input.
You can paste copied text as many times as you want.
SnipIt will un-hilight the selected area whenever any output occurs in
the highlighted window. You can still paste the copied text, however,
even though the highlighting has been removed.
Limitations of This Version
===========================
SnipIt can recognize any font in any height, only as long as that font
is fixed width and 8 pixels wide.
SnipIt in its current form cannot recognize text which is italicised,
underlined, or is drawn in certain colors. In some unusual colored text
cases, SnipIt will be 'blind' thinking it is seeing space characters,
and you will get nothing but spaces while pasting.
SnipIt can only recognize character codes between ASCII 32-127, so
special characters (requiring the ALT key to generate) will not get
recognized properly. If SnipIt cannot figure out a character, it will
substitute a '?' (question mark) character.
SnipIt appears to work properly with the ConMan replacement console
handler by William Hawes. SnipIt also appears to work properly with the
NEWCON: window of AmigaDOS 1.3. SnipIt may highlight areas in a
peculiar fashion in windows having the GIMMEZEROZERO attribute (eg.,
AmigaBasic).
This program will also co-operate with programs like SunMouse and others
which can change window activation automatically. However, note that
each character of any pasted text will arrive in whatever window the
mouse is currently in.
New Features of Version 1.2
===========================
Automatically runs in the background
------------------------------------
You no longer need to 'run' SnipIt- the program is now capable of
detaching itself and running automatically in the background.
Snips from both consoles and regular windows
--------------------------------------------
SnipIt can now recognize text in plain old windows (not only just
console windows anymore). So, applications like WPLibrary P-Edit and
VT100 terminal programs can be 'snipped' from. Note that SnipIt assumes
that text is being displayed in the window is some kind of cell array
(like a terminal). It probably won't do what you want in programs like
Deluxe Paint, and others which can place text anywhere in the window.
Built in mini-help
------------------
SnipIt will give you a quick rundown of its options if you type:
> snipit h
or
> snipit ?
Prestring insertion while pasting
---------------------------------
The program now provides an option to insert a short text string
before each line of characters as it is pasted. This can be useful
if you are 'snipping' text which you wish to 'quote'. You do this
by depressing the LEFT-ALT key (by default), instead of the
LEFT-AMIGA key while pasting. For example, if I snip, and then
paste this paragraph using LEFT-ALT, I get:
> The program now provides an option to insert a short text string
> before each line of characters as it is pasted. This can be useful
> if you are 'snipping' text which you wish to 'quote'. You do this
> by depressing the LEFT-ALT key (by default), instead of the
> LEFT-AMIGA key while pasting. For example, if I snip, and then
> paste this paragraph using LEFT-ALT, I get:
Note, a "> " (the default) string has been prepended to each pasted
line. This string can be changed at any time by:
> snipit p "the prestring: "
where the text appears between quotes after a "p". Actually, you can
use any delimiter, and not only quotes, like:
> snipit p .the prestring: .
Just repeat the initial character at the end. Your prestring must
contain no more than 32 characters.
Character cell location adjustments
-----------------------------------
Sometimes, in non-console windows, the text may not be placed in
positions that SnipIt can locate. SnipIt 1.2 now provides options that
allow you to slightly adjust its idea of where characters are located in
the window:
> snipit x +2 y -1
will move the snip area in windows, right by 2 pixels and up by one. If
you find that SnipIt is producing lots of ???????s while pasting, then
you may need to use this option to adjust the cell area (highlighted
area) slightly. For example, P-Edit currently requires:
> snipit x -1
as text characters are draw one pixel higher than SnipIt would otherwise
assume. Dave Wecker's VT100 currently requires:
> snipit y -1
You can also correct the x and y cell positions in console windows using
the 'u' and 'v' options:
> snipit u -3 v +1
will move the snip area in consoles, left by 3 pixels, and down by one.
For example, Eric Haberfellner's Handshake (VT100 emulator) currently
needs:
> snipit v +3
In most circumstances, you shouldn't need to use the 'u' and 'v' options
to adjust for console windows.
Improved recognition
--------------------
SnipIt can now recognize highlighted and inverted characters- you no
longer have to move that darn cursor away from your text.
Freeze windows while snipping
-----------------------------
If you type:
> snipit l 1
("l" for 'lock') Snipit 1.2 will freeze the window or console which you
are snipping from. This can be useful if you are trying to 'snip' text
in a window that would otherwise scroll.
> snipit l 0
turns this option off.
Re-assignable keyboard use
--------------------------
Normally, you snip and paste using the LEFT-AMIGA key; you can paste
with a prestring using the LEFT-ALT key while pasting. These key
choices can be changed. You change the normal, or Command-A, key from
the LEFT-AMIGA to another key by:
> snipit a <hexcode>
where the <hexcode> is from this table:
LEFT-SHIFT .... 0001
RIGHT-SHIFT ... 0002
CONTROL ....... 0008
LEFT-ALT ...... 0010 <- default Command-B key
RIGHT-ALT ..... 0020
LEFT-AMIGA .... 0040 <- default Command-A key
RIGHT-AMIGA ... 0080
other values won't work. So, to use the CONTROL key instead, you:
> snipit a 0008 (or just 8, you don't need the leading 0s).
The Command-B key, normally the LEFT-ALT key, can be changed, for
example, to the Right-Shift key:
> snipit b 0002
Default settings
----------------
By default snipit acts as though you had done:
> snipit p"> " l0 u0 v0 x0 y0 a0040 b0010
meaning:
o (p) use "> " as the prestring when pasting with the Command-B key
o (l) don't freeze the window being snipped from
o (u, v) no adjustment to cell area when snipping from consoles
o (x, y) no adjustment to cell area when snipping from windows
o (a) use LEFT-AMIGA for Command-A operation- regular snips and pastes
o (b) use LEFT-ALT for Command-B operation- insert prestring on pastes
Bugs
====
I have not gone to any special effort to check if Windows or Screens are
closed, or otherwise disappear, while the mouse is being used to
highlight a text area. The system will likely Guru if this happens.
SnipIt only works properly with the usa0 keymap (more below). Dvorak
(usa2) will not, and certain non-usa keyboards/keymaps may not work
properly with SnipIt. However, a 'patch' program is included to modify
SnipIt to work with other keymaps. See the file "PATCH.DOC" for more
information.
Ideas for the Future
====================
In approximate order of importance to me:
The next SnipIt will hopefully do a better job in dealing with KeyMaps.
Currently, SnipIt uses a hardcoded table of keycodes for pasting
character codes into the input stream. I'm not real happy with this,
because it is not the best design. This will be fixed next.
Recognize, as an option, ALL characters, even ones requiring the ALT key
to generate (full 8-bit ASCII).
An 'appending' snip. The next version of SnipIt will probably allow you
to 'append' or add newly snipped material to the end of previously
snipped text. This way, you could actually 'compose' a message by
collecting text from different parts of one or several windows. The
Command-B key is planned for this use while snipping.
Send snipped text to a device or file instead of into the input stream.
This way, you could direct snipped text into a PIPE:, for example.
Use the clipboard- some day.
Recognize text that isn't 8 pixels wide, is colored, underlined or
italicised. Don't hold your breath on these.
The SnipIt program acts like 2 different programs:
1. As the resident SnipIt program doing the real work.
2. As the user interface communicating options to the resident SnipIt.
Currently, the resident SnipIt also carries the code used by the user
interface portion. This is a mild waste of memory (less than 5K). A
future version of SnipIt may release code sections not required for the
resident portion, thereby reducing consumption of memory.
==========================================================================
Comments and contributions to:
------------------------------
plink: SCOTT E
bix: s_evernden
cis: 73116,3451
uucp: {ames,rutgers}!harvard!m2c!applix!scott
scott@applix.m2c.org
Scott Evernden
9 Courtland St.
Holliston, MA 01746
SHAR_EOF
# End of shell archive
exit 0
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.